package com.zktravel.util;

import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import javax.validation.Validator;

import org.springframework.util.StringUtils;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;

import com.google.common.collect.Lists;
import com.odianyun.util.ArrayUtils;
import com.odianyun.util.reflect.ReflectUtils;
import com.odianyun.util.value.ValueUtils;
import com.zktravel.core.exception.ServiceException;
import com.zktravel.enums.CodeEnum;
import com.zktravel.enums.ICodeMessage;

public abstract class ValidUtils {


	public static String extractErrorMessage(MethodArgumentNotValidException e) {
		FieldError fe = e.getBindingResult().getFieldError();

		String errmsg = fe.getDefaultMessage();
		if (errmsg != null && errmsg.startsWith("{") && errmsg.endsWith("}")) {
			errmsg = errmsg.substring(1, errmsg.length() - 1);
		}

		String modelName = CommonHelper.getModelName(fe.getObjectName());
		String i18n = LangUtils.getMsg(StringUtils.capitalize(modelName) + "." + fe.getField(), "");
		return getValidExtraMsg() + i18n + errmsg;
	}
	
	private static String getValidExtraMsg() {
		String extraErrMsg = CommonHelper.getValidExtraMsg();
		if (extraErrMsg == null) return "";
		return extraErrMsg;
	}
	
	public static String extractErrorMessage(ConstraintViolationException e) {
		Set<ConstraintViolation<?>> violations = e.getConstraintViolations();

		List<String> msgs = Lists.newArrayListWithExpectedSize(violations.size());

		if (!violations.isEmpty()) {
			for (ConstraintViolation<?> violation : violations) {
				Object bean = violation.getLeafBean();
				if (bean != null) {
					String modelName = CommonHelper.getModelName(bean.getClass().getSimpleName());
					Path path = violation.getPropertyPath();
					String pathStr = path.toString();
					String field = pathStr.substring(pathStr.lastIndexOf(".") + 1);

					String errmsg = violation.getMessage();
					if (errmsg != null && errmsg.startsWith("{") && errmsg.endsWith("}")) {
						errmsg = LangUtils.getMsgWithDefault(errmsg.substring(1, errmsg.length() - 1));
					}

					String i18n = LangUtils.getMsg(modelName + "." + field, "");

					msgs.add(getValidExtraMsg() + i18n + errmsg);
				}
			}

			return ArrayUtils.join(msgs.toArray(new String[msgs.size()]), ", ");
		}

		return e.getMessage();
	}
	public static void notNull(Object obj) {
		if (isNull(obj)) {
			throwError(LangUtils.getMsgWithDefault(CodeEnum.PARAMETER_NOT_NULL.getMessage()));
		}
	}
	
	public static void notNull(Object...objs) {
		for(Object obj : objs) {
			if (isNull(obj)) {
				throwError(LangUtils.getMsgWithDefault(CodeEnum.PARAMETER_NOT_NULL.getMessage()));
			}
		}
	}
	
	public static void notNull(Object obj, ICodeMessage codeMsg) {
		if (isNull(obj)) {
			throwError(codeMsg.getMessage());
		}
	}

	public static void notEmpty(Object[] obj) {
		if (isEmpty(obj)) {
			throwError(LangUtils.getMsgWithDefault(CodeEnum.PARAMETER_NOT_EMPTY.getMessage()));
		}
	}

	public static void notEmpty(Collection<?> coll) {
		if (isEmpty(coll)) {
			throwError(LangUtils.getMsgWithDefault(CodeEnum.PARAMETER_NOT_EMPTY.getMessage()));
		}
	}


	public static void fieldNotNull(Class<?> objClass, String field, Object value) {
		if (isNull(value)) {
			String code = CommonHelper.getModelName(objClass.getSimpleName()) + "." + field;

			String msg = LangUtils.getMsgWithDefault(code)
					+ LangUtils.getMsgWithDefault(CodeEnum.NOT_NULL.getMessage());

			throwError(msg);
		}
	}
	
	public static void fieldNotNull(Object obj, String ...fields) {
		 for(String field:fields){
			   Object value = ReflectUtils.callGetMethod(obj, field);
			   fieldNotNull(obj.getClass(), field, value);
		 }
		
	}

	public static void fieldNotEmpty(Object obj, String field) {
		Object[] values = (Object[]) ReflectUtils.callGetMethod(obj, field);
		fieldNotEmpty(obj.getClass(), field, values);
	}

	public static void fieldNotEmpty(Class<?> objClass, String field, Object[] values) {
		if (isEmpty(values)) {
			String code = CommonHelper.getModelName(objClass.getSimpleName()) + "." + field;

			String msg = LangUtils.getMsgWithDefault(code)
					+ LangUtils.getMsgWithDefault(CodeEnum.NOT_EMPTY.getMessage());

			throwError(msg);
		}
	}


	public static void fieldNotZero(Object obj, String field) {
		Number value = (Number) ReflectUtils.callGetMethod(obj, field);
		fieldNotZero(obj.getClass(), field, value);
	}

	public static void fieldNotZero(Class<?> objClass, String field, Number value) {
		fieldNotNull(objClass, field, value);

		Number zero = ValueUtils.convert(0, value.getClass());
		if (value.equals(zero)) {
			String code = CommonHelper.getModelName(objClass.getSimpleName()) + "." + field;
			String msg = LangUtils.getMsgWithDefault(code) + LangUtils.getMsgWithDefault(CodeEnum.NOT_EMPTY.getMessage());

			throwError(msg);
		}
	}

	public static boolean isNull(Object value) {
		if (value == null) {
			return true;
		}

		if (value instanceof String && StringUtils.isEmpty((String) value)) {
			return true;
		}

		return false;
	}

	public static boolean isEmpty(Collection<?> coll) {
		return coll == null || coll.size() == 0;
	}

	public static boolean isEmpty(Object[] values) {
		return values == null || values.length == 0;
	}

	/**
	 * 判断field在objClass对应的实体中不存在时的错误
	 * @param objClass
	 * @param field
	 * @return
	 */
	public static String getNotExistsMsg(Class<?> objClass, String field) {
		String model = CommonHelper.getModelName(objClass.getSimpleName());
		String code = model + "." + field;
		String modelName = LangUtils.getMsgWithDefault(model);
		String fieldName = LangUtils.getMsgWithDefault(code);
		return fieldName + LangUtils.getMsgWithDefault(CodeEnum.NOT_EXISTS.getMessage(), new String[]{modelName});
	}

	public static String getNotExistsMsg(String modelMsg, String fieldMsg) {
		return fieldMsg + LangUtils.getMsgWithDefault(CodeEnum.NOT_EXISTS.getMessage(), new String[]{modelMsg});
	}

	/**
	 * 判断field在objClass对应的实体中存在时的错误
	 * @param objClass
	 * @param field
	 * @return
	 */
	public static String getExistsMsg(Class<?> objClass, String field) {
		String model = CommonHelper.getModelName(objClass.getSimpleName());
		String code = model + "." + field;
		String modelName = LangUtils.getMsgWithDefault(model);
		String fieldName = LangUtils.getMsgWithDefault(code);
		return fieldName + LangUtils.getMsgWithDefault(CodeEnum.EXISTS.getMessage(), new String[]{modelName});
	}

	public static String getExistsMsg(String modelMsg, String fieldMsg) {
		return fieldMsg + LangUtils.getMsgWithDefault(CodeEnum.EXISTS.getMessage(), new String[]{modelMsg});
	}

	public static void validate(Object bean, Validator validator) {
		Set<ConstraintViolation<Object>> violations = validator.validate(bean);
		if (! violations.isEmpty()) {
			throw new ConstraintViolationException(violations);
		}
	}

	public static void validateProperty(Object bean, String property, Validator validator) {
		Set<ConstraintViolation<Object>> violations = validator.validateProperty(bean, property);
		if (! violations.isEmpty()) {
			throw new ConstraintViolationException(violations);
		}
	}

	private static void throwError(String errmsg) {
		throw new ServiceException(errmsg);
	}

}
